#include <iostream>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
#include "Socket.hpp"
#include "Calculator.hpp"
#include "Protocol.hpp"
#include "Factory.hpp"
using namespace std;

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        cout << "Incorrect use, correct use:\n"
             << "    " << argv[0] << " ip port" << endl;
    }

    string serverip = argv[1];
    uint16_t serverport = stoi(argv[2]);
    Socket *sock = new TcpSocket();
    sock->BuildClientSocket(serverip, serverport);
    unique_ptr<Factory> ft(new Factory());
    unique_ptr<Protocol> pro(new Protocol());

    srand(time(nullptr) ^ getpid());
    string opers = "+-*/%^=";

    while (true)
    {
        // 1. 构建需求
        int x = rand() % 100;
        int y = rand() % 100;
        char op = opers[rand() % opers.size()];
        shared_ptr<Calculator::Request> req = ft->BuildCalRequest(x, y, op);
        // 2. 序列化结构字段
        string request;
        req->Serialize(request);
        // 3. 封装报文
        string message;
        pro->Package(request, &message);
        // 4. 发送报文
        sock->Send(message);
        // 5. 接收响应报文
        string response;
        sock->Recv(response, 1024);
        // 5. 响应报文解包
        string content;
        pro->Unpackage(response, &content);
        // 6. 有效载荷反序列化
        shared_ptr<Calculator::Response> rep = ft->BuildCalResponse();
        rep->Deserialize(content);
        cout << req->GetX() << " " << req->GetOp() << " " << req->GetY() << " = " << rep->GetResult() << "[" << rep->GetCode() << "]" << endl;
    }

    return 0;
}
